package com.solidtrust.admin.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.solidtrust.admin.service.ImageExtractor;
import com.solidtrust.app.FileSystemUtil;
import com.solidtrust.crawler.service.ImageService;
import com.solidtrust.crawler.service.ImageService._Image;
import com.solidtrust.dao.CommonDao;
import com.solidtrust.entity.CarImage;




@Controller
@RequestMapping("img")
public class ImageAdminController {

	private static final Logger log4j = Logger.getLogger(ImageAdminController.class);
	
	@PersistenceContext
	private EntityManager em;
	
	@Autowired ImageExtractor extractor;
	@Autowired ImageService service;
	@Autowired CommonDao commonDao;
	
	@RequestMapping("index")
	public String search(
			@RequestParam(value="page", required=false, defaultValue="1") Integer pageIndex, 
			@RequestParam(value="pageSize", required=false, defaultValue="20") Integer pageSize,
			String brand, String brandType, String subBrand,
			Model model){
		
		if(brand != null){
			Pageable pageable = new PageRequest(pageIndex - 1, pageSize);
			
			String ql = "from CarImage c where brand = '" + brand + "'"; 
			if(StringUtils.isNotEmpty(brandType)){
				ql += " and brandType = '" + brandType + "'";
			}
			if(StringUtils.isNotEmpty(subBrand)){
				ql += " and subBrand = '" + subBrand + "'";
			}
			
			String countQl = "select count(c) " + ql;
			List<CarImage> list = em.createQuery(ql, CarImage.class)
					.setMaxResults(pageable.getPageSize())
					.setFirstResult(pageable.getOffset())
					.getResultList();
			Long count = em.createQuery(countQl, Long.class).getSingleResult();
			Page<CarImage> page = new PageImpl<>(list, pageable, count.intValue());
			model.addAttribute("page", page);
			model.addAttribute("brand", brand);
			model.addAttribute("subBrand", subBrand);
			model.addAttribute("brandType", brandType);
		}
		return "admin/img/index.jsp";
	}
	
	@Transactional(readOnly = true)
	@ResponseBody
	@RequestMapping("getCategories")
	public List<String> getCategories(Integer level, String brand, String brandType, String subBrand){
		String ql = null;
		if(level == 0){
			ql = "select distinct brand from CarImage";
		}
		
		else if(level == 1){
			ql = "select distinct brandType from CarImage where brand = '" + brand + "'";
		}
		
		else if(level == 2){
			ql = "select distinct subBrand from CarImage where brand = '" + brand + "'";
			if(StringUtils.isNotBlank(brandType)){
				ql += " and brandType = '" + brandType + "'";
			}
		}
		
		else if(level == 3){
			ql = "select distinct build from CarImage where brand = '" + brand + "' and subBrand = '" + subBrand + "'";
			if(StringUtils.isNotBlank(brandType)){
				ql += " and brandType = '" + brandType + "'";
			}
		}
		
		if(ql == null){
			return null;
		}
		return em.createQuery(ql, String.class).getResultList();
	}
	
	@RequestMapping(value = "/serve/{filename:.+}")
	public void serveImage(HttpServletRequest req, HttpServletResponse resp, 
			@PathVariable("filename") String filename,
			String s) throws IOException{
		String filepath = filename;
		//404
		File f = new File("l".equals(s) ? FileSystemUtil.getCarImage() : FileSystemUtil.getCarThumb(), filepath);
		if(!f.exists()){
			resp.sendError(HttpServletResponse.SC_NOT_FOUND);
			return;
		}
		
		//304
		long lastModifiedTimestamp = f.lastModified();
		long ifModifiedSince = req.getDateHeader("If-Modified-Since");
		boolean notModified = (ifModifiedSince >= (lastModifiedTimestamp / 1000 * 1000));
		if (notModified) {
			resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
			return;
		}
		else {
			resp.setDateHeader("Last-Modified", lastModifiedTimestamp);
		}
		
		//length
		resp.setContentLength((int) f.length());
		
		//content type
		resp.setContentType("image/jpg");
		
		//response
		FileCopyUtils.copy(new FileInputStream(f), resp.getOutputStream());
	}
	
	@Transactional(readOnly=false)
	@RequestMapping(value = "/del/{id}")
	public @ResponseBody int delete(@PathVariable(value="id") int id,
			Model model) throws Exception{
		CarImage ip = em.find(CarImage.class, id);
		em.remove(ip);
		log4j.info("Removed CarImage with ID:" + id);
		return 1;
	}
	
	@RequestMapping(value = "/save")
	public @ResponseBody String save(@RequestParam(value="index") int index,
			@RequestParam(value="imageProductId") int imageProductId,
			@RequestParam(value="url", required=false) String url,
			@RequestParam(value="imageId", required=false) String imageId,
			@RequestParam(value="file", required=false) MultipartFile file) throws Exception{
		CarImage imageInfo = em.find(CarImage.class, imageProductId);
		setImage(imageInfo, ImageExtractor.getImageFilename(imageInfo.getSubBrandId(), index), index);
		
		if(StringUtils.isNotEmpty(url)){
			extractor.scrape(url, imageInfo, index);
		}
		else if(StringUtils.isNotEmpty(imageId)){
			String url1 = service.scrapeUrlBySubBrandId(imageInfo, imageId, index);
			extractor.scrape(url1, imageInfo, index);
		}
		else if(file != null){
			extractor.scrape(file, imageInfo, index);
		}
		commonDao.save(imageInfo);
		return ImageExtractor.getImageFilename(imageInfo.getSubBrandId(), index) + "?t=" + System.currentTimeMillis();
	}
	
	@RequestMapping(value = "/saveBatch")
	public @ResponseBody int saveBatch(
			@RequestParam(value="imageProductId") int imageProductId,
			@RequestParam(value="urls") String[] urls) throws Exception{
		CarImage imageInfo = em.find(CarImage.class, imageProductId);
		
		for (int index = 0; index < urls.length; index++) {
			try {
				setImage(imageInfo, ImageExtractor.getImageFilename(imageInfo.getSubBrandId(), index), index);
				extractor.scrape(urls[index], imageInfo, index);
				imageInfo.setStatus(1);
			} catch (Exception e) {
				log4j.error(e.getMessage(), e);
			}
		}
		commonDao.save(imageInfo);
		return 1;
	}
	
	@Transactional(readOnly=false)
	@RequestMapping(value = "/order/{id}")
	public @ResponseBody int order(@PathVariable(value="id") int id,
			@RequestParam(value="srcIndex") int src,
			@RequestParam(value="tgtIndex") int tgt){
		CarImage ip = em.find(CarImage.class, id);
		String srcUrl = getImage(ip, src);
		String tgtUrl = getImage(ip, tgt);
		setImage(ip, srcUrl, tgt);
		setImage(ip, tgtUrl, src);
		em.persist(ip);
		return 1;
	}
	
	@RequestMapping(value = "/thumbs")
	public @ResponseBody List<_Image> getImageList(String subBrandId) throws IOException{
		return service.scrapeImageList(subBrandId);
	}
	
	private String getImage(CarImage ip, int index){
		if(index == 0){
			return ip.getImage1();
		}
		if(index == 1){
			return ip.getImage2();
		}
		if(index == 2){
			return ip.getImage3();
		}
		if(index == 3){
			return ip.getImage4();
		}
		return null;
	}
	
	private void setImage(CarImage ip, String img, int index){
		if(index == 0){
			ip.setImage1(img);
		}
		if(index == 1){
			ip.setImage2(img);
		}
		if(index == 2){
			ip.setImage3(img);
		}
		if(index == 3){
			ip.setImage4(img);
		}
	}
}
